home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turnbull China Bikeride
/
Turnbull China Bikeride - Disc 2.iso
/
BARNET
/
COMPILER
/
SATHER
/
!Sather
/
System
/
Common
/
h
/
exception
< prev
next >
Wrap
Text File
|
1997-01-14
|
5KB
|
148 lines
/*
* Copyright (C) International Computer Science Institute, 1994. COPYRIGHT
* NOTICE: This code is provided "AS IS" WITHOUT ANY WARRANTY and is subject
* to the terms of the SATHER LIBRARY GENERAL PUBLIC LICENSE contained in
* the file "Doc/License" of the Sather distribution. The license is also
* available from ICSI, 1947 Center St., Suite 600, Berkeley CA 94704, USA.
* ---> Please email comments to "sather-bugs@icsi.berkeley.edu".
*/
#ifndef PSATHER
#ifndef _EXC_SATHER_H_
#define _EXC_SATHER_H_
#include <stddef.h>
#include <stdlib.h>
#if !defined (__riscos__)
# include <sys/utsname.h>
#endif
#if defined(V_RISCOS) && defined(R_5_0) /* yoshida@agusa.nuie.nagoya-u.ac.jp */
# ifndef SETJMP_H
# define SETJMP_H
# include <setjmp.h>
# endif
#else
# include <setjmp.h>
#endif
#include <assert.h>
/*
* the structure EXCEPT_ELEMENT should not be used anywhere in the code
*/
struct EXCEPT_ELEMENT {
struct EXCEPT_ELEMENT *next;
jmp_buf jmp;
OB exception;
short mark;
};
/*
* to use this code, you must define in ONE *.c file
* DEFINE_EXCEPTION_STACK outside any function to declare a global variable.
* or include this file in one *.c file after you've defined RUNTIME
*/
#define DEFINE_EXCEPTION_STACK static struct EXCEPT_ELEMENT exp_bottom;struct EXCEPT_ELEMENT *EXCEPTION_STACK=&exp_bottom
#ifndef RUNTIME
extern struct EXCEPT_ELEMENT *EXCEPTION_STACK;
#else
DEFINE_EXCEPTION_STACK;
#endif
/*
* While executing a lock, try or protect statement, an exception stack
* is build. You can mark specific stack frames and unwind the stack to the
* first mark at any time. You have 16 different mark (0-15), but MARK(0)
* and MARK(1) are predefined. The first is used to mark the stack at the
* beginning of a function, while the second can be used for loops.
* Be warned however, that while ESCAPE unwinds the stack end ends the
* function, JUMP_OUT_OF_LOOP does NOT terminate the loop. You have to
* manually end the loop by either a break or a goto.
*/
#define MARK(n) (1<<(n))
#define MARK_FUNCTION MARK(0)
#define MARK_LOOP MARK(1)
#define SET_EXCEPTION_MARK(n) EXCEPTION_STACK->mark|=(n)
#define REMOVE_EXCEPTION_MARK(n) EXCEPTION_STACK->mark&= ~(n)
#define POP_TO(m) do { while(EXCEPTION_STACK->mark&(m)==0) EXCEPTION_STACK=EXCEPTION_STACK->next; REMOVE_EXCEPTION_MARK(m) } while(0)
/*
* each function using ESCAPE MUST use EXCEPTION_PROLOGUE at the
* beginning, and EXCEPTION_EPILOGUE at the end. Such a function may
* NOT use return.
*/
#define EXCEPTION_PROLOGUE SET_EXCEPTION_MARK(MARK_FUNCTION);
#define EXCEPTION_EPILOGUE REMOVE_EXCEPTION_MARK(MARK_FUNCTION);
#define ESCAPE POP_TO(MARK_FUNCTION);return
/*
* If you want to use mark on the stack to end loops, use
* LOOP_BEGIN before the loop and LOOP_END at its end.
* Note that JUMP_OUT_OF_LOOP must be followed by a break or goto,
* as it will not end the loop.
*/
#define LOOP_BEGIN SET_EXCEPTION_MARK(MARK_LOOP);
#define LOOP_END REMOVE_EXCEPTION_MARK(MARK_LOOP);
#define JUMP_OUT_OF_LOOP POP_TO(MARK_LOOP)
/*
* To pop some frames from the exception stack, you may use POP_EXCEPTION.
* This macro can be used instead of LOOP_BEGIN and LOOP_END. The only
* problem is that you must know exactly how many frames to pop
* when exiting a loop.
*/
#define POP_EXCEPTION1 EXCEPTION_STACK=EXCEPTION_STACK->next
#define POP_EXCEPTION(n) do { int i=n;while(i-->0) POP_EXCEPTION1; } while(0)
/*
* RAISE(x) raises an exception. The value x (actually a pointer) is passed
* to the exception handling routine, which can use it through the
* macro EXCEPTION. If this routine needs to propagate the exception,
* it can use RAISE(EXCEPTION)
*/
#define UNCAUGHT_EXCEPTION 0
/* This macro is somewhat tricky since ex could be instantiated with EXCEPTION
* when propagating the exception to the handler above. If so,
* EXCEPTION is expanded into EXCEPTION_STACK->exception, but EXCEPTION_STACK
* is changed in the macro and a horrible name capture happens. To avoid it,
* we need to copy "ex" into local "the_ex" immediately and use "the_ex"
* everywhere.
* Fixed on 8/23/96
* Boris
*/
#define RAISE(ex) do { OB the_ex = ex; \
struct EXCEPT_ELEMENT *PREV_EXCEPTION_STACK=EXCEPTION_STACK; \
EXCEPTION_STACK=PREV_EXCEPTION_STACK->next; \
if(PREV_EXCEPTION_STACK->next!=NULL) { \
EXCEPTION_STACK->exception=the_ex; \
longjmp(PREV_EXCEPTION_STACK->jmp,1); \
} else assert(UNCAUGHT_EXCEPTION); \
} while(0)
#define EXCEPTION ((OB)EXCEPTION_STACK->exception)
/*
* To protect some statements A against exception, use
* PROTECT_BEGIN
* A;
* PRTOECT_WHEN
* if(EXCEPTION==....
* PRTOECT_END
* If PROTECT_END is ever executed because the exception handler does
* neither end the program, nor raise another exceptioexception or ESCAPE
* (see above), the exception is automatically propagated back to the
* next PROTECT by a RAISE(EXCEPTION).
*/
#define PROTECT_BEGIN { struct EXCEPT_ELEMENT p_n; \
if(setjmp(p_n.jmp)==0) { \
p_n.next=EXCEPTION_STACK; \
p_n.mark=0; \
EXCEPTION_STACK= &p_n;
#define PROTECT_WHEN POP_EXCEPTION1; } else {
#define PROTECT_END } \
}
#endif
#endif